/**
 * 
 */
package com.app.gameserver.http;

import java.net.InetSocketAddress;

import org.apache.log4j.Logger;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.handler.codec.http.HttpHeaders;
import org.jboss.netty.handler.codec.http.HttpMethod;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;
import org.jboss.netty.handler.codec.http.HttpVersion;

import com.app.framework.context.ActionRequest;
import com.app.framework.context.Context;
import com.app.framework.context.Request;
import com.app.framework.exception.ClientException;
import com.app.framework.exception.FrameException;
import com.app.framework.handler.GameUpstreamHandler;
import com.app.framework.http.HttpContext;
import com.app.framework.http.HttpResponse;
import com.app.framework.http.HttpServiceRequest;
import com.app.framework.util.ErrorCodeConstants;
import com.app.framework.util.StringUtils;
import com.app.gameserver.service.http.SessionService;

/**
 * @author lisong
 * @version 2013-2-26 下午2:18:29
 */
public class HttpUpstreamHandler extends GameUpstreamHandler {

	private static final Logger logger = Logger.getLogger(HttpUpstreamHandler.class);

	public HttpUpstreamHandler(int type) {
		super(type,false);
	}
	@Override
	public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
			throws Exception {

		HttpRequest request = (HttpRequest)e.getMessage();
		
		HttpMethod hm = request.getMethod();
		
			if(!HttpMethod.POST.equals(hm)) {
				
				logger.error("the request is not post method");
				
				throw new ClientException("the request is not post method");
			}

			long contentLength = HttpHeaders.getContentLength(request);
			
			ChannelBuffer cb = request.getContent();
			
			byte[] content = cb.array();
			
			if(contentLength != content.length) {
				StringBuilder sb = new StringBuilder();
				sb.append("Transmission loss of data ").append("contentLength:").append(contentLength).append(" data real length:").append(content.length);
				String msg = sb.toString();
				logger.error(msg);
				
				throw new ClientException(msg);
			}
			Request req = null;
			
			String cmd = request.getHeader(REQUEST_QUERY_STRING);
			
			if(StringUtils.isNullOrEmpty(cmd)) {
				throw new ClientException("cmd can't be empty or null",ErrorCodeConstants.CLIENT_ERROR_CMD_NOT_CONTAIN);
			}
			
			int requestTypeId = Integer.parseInt(cmd);//请求类型 action还是service
			
			String ip = ((InetSocketAddress)e.getRemoteAddress()).getAddress().getHostAddress();
			
			HttpResponse response =  new HttpResponse(HttpVersion.HTTP_1_1,HttpResponseStatus.OK,e.getChannel());
			
			if(requestTypeId == ActionRequest.TYPE ) {//如果是action请求
				
				short actionId = Short.parseShort(request.getHeader(REQUEST_ACTION_NAME_STRING));
				
				String userId = request.getHeader(REQUEST_USERUID_STRING);
				
				String sessionId = request.getHeader(REQUEST_SESSIONID_STRING);
				
				String requestId = request.getHeader(REQUEST_ID_STRING);
				
				int reqId = 0;
				
				if(SessionService.CHECK_SESSION) {
					if(StringUtils.isNullOrEmpty(userId,sessionId,requestId)) {
						
						StringBuilder msg = new StringBuilder();
						
						msg.append("headers info incomplete for action request of check session ");
						
						msg.append("actionId:").append(actionId).append(",userId:").append(userId).append(",sessionId:"+sessionId).append(",requestId:").append(requestId);
						
						throw new ClientException(msg.toString(),ErrorCodeConstants.CLIENT_ERROR_ACTION_REQUEST_INCOMPLETE);
					}
					reqId = Integer.parseInt(requestId);
				}
				else {
					if(StringUtils.isNullOrEmpty(userId)) {
						
						StringBuilder msg = new StringBuilder();
						
						msg.append("headers info incomplete for action request of not check session ");
						
						msg.append("actionId:").append(actionId).append(",userId:").append(userId);
						
						throw new ClientException(msg.toString(),ErrorCodeConstants.CLIENT_ERROR_ACTION_REQUEST_INCOMPLETE);
					}
				}
				
				req = new ActionRequest(content,actionId, Long.parseLong(userId), ip);
				
				ActionRequest ar = (ActionRequest)req;
				
				ar.setSessionId(sessionId);
				
				ar.setRequestId(reqId);
			}
			else {//service请求
				
				short serviceId = Short.parseShort(request.getHeader(REQUEST_SERVICE_NAME_STRING));
				
				String methodName = request.getHeader(REQUEST_METHOD_NAME_STRING);
				
				if(StringUtils.isNullOrEmpty(methodName)) {
					throw new ClientException("headers info incomplete for service request",ErrorCodeConstants.CLIENT_ERROR_SERVICE_REQUEST_INCOMPLETE);
				}
				
				req = new HttpServiceRequest(content, serviceId, methodName, ip);
			}
			
			response.setRequest(req);
			
			Context context = new HttpContext(response);
			
			context.execute();
		
			context.close();
	}
	
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
			throws Exception {
		
		e.getCause().printStackTrace();
		
		logger.error(e.getCause());
		
		if(FrameException.class.isAssignableFrom(e.getCause().getClass())) {//已知异常下发给客户端,未知异常不处理 以免引起死循环(被循环调用该方法)
			
			FrameException fe = (FrameException)e.getCause();
			
			int code = fe.getCode();
			
			HttpResponse response =  new HttpResponse(HttpVersion.HTTP_1_1,HttpResponseStatus.OK,e.getChannel());
			
			response.protocolException(code,  e.getCause().getMessage());
		}
	}
}
